#include <stdio.h>
#include <unistd.h>
#include <iostream>

class CData {
public:
    CData() = delete;
    CData(const char* ch) : data(ch) {    // 构造函数，涉及资源的复制
        std::cout << "CData(const char* ch)" << std::endl;
    }
    CData(const std::string& str) : data(str) { // 拷贝构造函数，涉及资源的复制
        std::cout << "CData(const std::string& str)" << std::endl;
    }
    CData(std::string&& str) : data(str) {  // 移动构造函数，不涉及资源的复制
        std::cout << "CData(std::string&& str)" << std::endl;
    }
    ~CData() {  // 析构函数
        std::cout << "~CData()" << std::endl;
    }
private:
    std::string data;   // 表示内部管理的资源
};

/**
1）不使用std::forward实现
假设我们不使用std::forward，那么要提高函数参数转发效率，我们使用右值引用（万能引用）作为模板函数参数：
*/
// template<typename T>
// CData* Creator(T&& t){  // 利用&&万能引用，引用折叠：T&& && -> T&&; T&& & -> T&
//     return new CData(t);
// }

/**
2）使用std::forward实现
使用std::forward即可完美解决上述问题：
*/
template<typename T>
CData* Creator(T&& t){  // 利用&&万能引用，引用折叠：T&& && -> T&&; T&& & -> T&
    return new CData(std::forward<T>(t));
}

int main() {
    std::string str1 = "hello";
    std::string str2 = " world";
    CData *p1 = Creator(str1);      // 参数折叠为左值引用，调用CData构造函数
    // CData *p2 = Creator(str1 + str2);  // 参数折叠为右值引用，但在Creator函数中t仍为左值，调用CData构造函数！！！
    CData *p2 = Creator(str1 + str2);   // 参数折叠为右值引用，通过std::forward转发给CData，调用移动构造函数

    delete p2;
    delete p1;
    return 0;
}